package me.ingxin.android.tools;

import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.text.TextUtils;

import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class ProcessUtils {

    private static final String[] processName = {null};

    public static boolean isInMainProcess(Context context) {
        String mainProcessName = null;
        if (context.getApplicationInfo() != null) {
            mainProcessName = context.getApplicationInfo().processName;
        }
        if (TextUtils.isEmpty(mainProcessName)) {
            mainProcessName = context.getPackageName();
        }

        String processName = getProcessName(context);
        if (processName == null || processName.isEmpty()) {
            processName = "";
        }
        return TextUtils.equals(processName, mainProcessName);
    }

    public static String getProcessName(Context context) {
        if (processName[0] == null) {
            synchronized (processName) {
                if (processName[0] == null) {
                    processName[0] = getProcessNameInternal(context);
                }
            }
        }
        return (processName[0] != null ? processName[0] : "");
    }

    private static String getProcessNameInternal(final Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            return Application.getProcessName();
        }

        try {
            final int myPid = Process.myPid();
            final int myUid = Process.myUid();
            final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            if (am != null) {
                final List<ActivityManager.RunningAppProcessInfo> procInfos = am.getRunningAppProcesses();
                if (procInfos != null) {
                    for (ActivityManager.RunningAppProcessInfo procInfo : procInfos) {
                        if (procInfo.pid == myPid && procInfo.uid == myUid) {
                            return procInfo.processName;
                        }
                    }
                }
            }
        } catch (Throwable ignored) {
            // Ignored.
        }

        final byte[] buf = new byte[2048];
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream("/proc/self/cmdline"));
            int len = in.read(buf);
            while (len > 0 && (buf[len - 1] <= 0 || buf[len - 1] == 10 || buf[len - 1] == 13))
                --len;
            if (len > 0) {
                return new String(buf, StandardCharsets.US_ASCII);
            }
        } catch (Throwable thr) {
            thr.printStackTrace();
        } finally {
            closeQuietly(in);
        }

        return null;
    }


    public static void closeQuietly(Object obj) {
        if (obj == null) return;
        if (obj instanceof Closeable) {
            try {
                ((Closeable) obj).close();
            } catch (Throwable ignored) {
                // Ignored.
            }
        } else if (obj instanceof AutoCloseable) {
            try {
                ((AutoCloseable) obj).close();
            } catch (Throwable ignored) {
                // Ignored.
            }
        } else {
            throw new IllegalArgumentException("obj: " + obj + " cannot be closed.");
        }
    }

}
